from datetime import date, datetime
import time
from google.appengine.api import users
from google.appengine.ext import db, search

class DictModel(object):
    SIMPLE_TYPES = (int, long, float, bool, dict, basestring, list)

    def to_dict(self):
        output = {}

        for key, prop in self.properties().iteritems():
            if key[0] == '_':
                continue
            value = getattr(self, key)

            if value is None or isinstance(value, self.SIMPLE_TYPES):
                output[key] = value
            elif isinstance(value, date) or isinstance(value, datetime):
                # Convert date/datetime to ms-since-epoch ("new Date()").
                ms = time.mktime(value.utctimetuple())
                ms += getattr(value, 'microseconds', 0) / 1000
                output[key] = int(ms)
            elif isinstance(value, db.GeoPt):
                output[key] = {'lat': value.lat, 'lon': value.lon}
            elif isinstance(value, DictModel):
                output[key] = value.to_dict()
            elif isinstance(value, db.Model):
                output[key] = value.key().id()
            elif isinstance(value, users.User):
                output[key] = {"id": value.user_id(), "name": value.nickname()}
            else:
                raise ValueError('cannot encode ' + repr(prop))

        output["id"] = self.key().id()

        return output

class Account(db.Model, DictModel):
    user = db.UserProperty(required=False, verbose_name="User")

class Service(db.Model, DictModel):
    name = db.StringProperty(required=True, verbose_name="Name")
    url = db.StringProperty(required=True, verbose_name="URL")

class ServiceAccount(db.Model, DictModel):
    account = db.ReferenceProperty(Account, required=True, verbose_name="Account")
    service = db.ReferenceProperty(Service, required=True, verbose_name="Service")

class CheckType(db.Model, DictModel):
    name = db.StringProperty(required=True, verbose_name="Name")
    code = db.IntegerProperty(required=True, verbose_name="Code")

class ServiceCheck(db.Model, DictModel):
    service = db.ReferenceProperty(Service, required=True, verbose_name="Service")
    check_type = db.ReferenceProperty(CheckType, required=True, verbose_name="Check type")

class ServiceCheckHistory(db.Model, DictModel):
    STATUS_OK = 0
    STATUS_DISRUPTION = 1
    STATUS_OFFLINE = 2
    STATUSES = (STATUS_OK, STATUS_DISRUPTION, STATUS_OFFLINE)

    service_check = db.ReferenceProperty(ServiceCheck, required=True, verbose_name="Service check")
    status_text = db.StringProperty(required=True, verbose_name="Status text")
    status = db.IntegerProperty(choices=STATUSES, required=True, verbose_name="Status")
    when = db.DateTimeProperty(auto_now_add=True, verbose_name="When")

if not CheckType.all().count():
    CheckType(name = "Http ping", code = 1).put()